// Dimensions of sunburst.
var width = $(".datacontent").width();
var height = 600;
var radius = Math.min(width, height) / 1.7;

// Breadcrumb dimensions: width, height, spacing, width of tip/tail.
var b = {
  w : 75,
  h : 90,
  s : 3,
  t : 10
};

// Mapping of step names to colors.
var colors = {
  "home" : "#5687d1",
  "index" : "#7b615c",
  "list" : "#de783b",
  "detail" : "#6ab975",
  "qy_detail" : "#a173d1",
  "post" : "#333333",
  "jianli_detail" : "#0066cc",
  "vip" : "#cc0033",
  "my" : "#EAD85A",
  "others" : "#003399",
  "end" : "#bbbbbb",
  "empty" : "#F98CC5",
  "login" : "#EAAE5A",
  "deliver" : "#109508",
  "other_biz": "#CB67F3"
};

// Total size of all segments; we set this later, after loading the data.
var totalSize = 0;

var vis;

var partition = d3.layout.partition().size([ 2 * Math.PI, radius * radius ])
    .value(function(d) {
      return d.size;
    });

var arc = d3.svg.arc().startAngle(function(d) {
  return d.x;
}).endAngle(function(d) {
  return d.x + d.dx;
}).innerRadius(function(d) {
  return Math.sqrt(d.y);
}).outerRadius(function(d) {
  return Math.sqrt(d.y + d.dy);
});

// init("");

/*d3.text("csv").header("X-Requested-With", "XMLHttpRequest").get(
    function(error, data) {
      setButton(data);
    });*/

/*function setButton(data) {

  var re = /\"\[DIR\]\"><\/td><td><a href=\"[\S\s]*?<\/a>/g; // 注意g将全文匹配，不加将永远只返回第一个匹配。
  var arr;
  var re2 = /[a-z0-9\-]+\//;
  var btnDiv = d3.select("#btns");
  while ((arr = re.exec(data)) != null) { // exec使arr返回匹配的第一个，while循环一次将使re在g作用寻找下一个匹配。

    var csvName = re2.exec(arr[0])[0];
    // console.log(csvName);
    var c = "initNew('" + csvName + "')";
    btnDiv.append("button").attr("onclick", c).text(csvName);
    // btnDiv.append("div");

  }
}*/

function initDiv(id, title) {

  d3.select("#main").remove();
  d3.select("#sidebar").remove();
  var mainDiv = d3.select("#" + id).append("div").attr("id", "main");
  // if (mainDiv) {mainDiv.remove()};
  // mainDiv.append("h2").text(title);
  var dataTitDiv = mainDiv.append('div').attr('class','dataTit');
  dataTitDiv.append('i').attr('class','mark');
  dataTitDiv.append('span').text(title);
  var sequenceDiv = mainDiv.append("div").attr("id", "sequence");

  var chartDiv = mainDiv.append("div").attr("id", "chart");

  var sidebarDiv = d3.select("#" + id).append("div").attr("id", "sidebar");
  sidebarDiv.append("input").attr("type", "checkbox").attr("id",
      "togglelegend");
  // sidebarDiv.text("Legend")
  sidebarDiv.append("br");
  sidebarDiv.append("div").attr("id", "legend").style("visibility", "");
}

/*function init(title) {

  initDiv("s1", title);

  vis = d3.select("#chart").append("svg:svg").attr("width", width).attr(
      "height", height).append("svg:g").attr("id", "container").attr(
      "transform", "translate(" + width / 2 + "," + height / 2 + ")");

  // Use d3.text and d3.csv.parseRows so that we do not need to have a header
  // row, and can receive the csv as an array of arrays.
  url = "csv/" + title;

  d3.text(url, function(text) {

    var csv = d3.csv.parseRows(text);
    var json = buildHierarchy(csv);
    // console.log(json);
    createVisualization(json);
  });
}*/
function initNew(title,jsonArr) {

  initDiv("s1", title);

  vis = d3.select("#chart").append("svg:svg").attr("width", width).attr(
      "height", height).append("svg:g").attr("id", "container").attr(
      "transform", "translate(" + width / 2 + "," + height / 2 + ")");

  // var jsonArr = new Array();

  // jsonArr = eval('('+jsonArr+')')

  createVisualization(jsonArr)

}

function setTree(json, jsonArr, depth) {
  var replaceNode;
  if (json.name != "root") {
    replaceNode = jsonArr[depth];
  } else {
    depth = -1;
    replaceNode = jsonArr[0];
  }
  if (!replaceNode) {
    return;
  } else if (!replaceNode.value) {
    return;
  }
  ;
  json.value = replaceNode.value;
  if (!json.children) {
    return;
  }
  ;
  for (var i = 0; i < json.children.length; i++) {
    var child = json.children[i];
    var childName = child.name;
    var jsonArr2 = new Array();
    for (var j = 0; j < jsonArr.length; j++) {
      if (!jsonArr[j]) {
        continue;
      } else if (!jsonArr[j].children) {
        continue
      }
      ;
      childrenArr = jsonArr[j].children;
      for (var k = 0; k < childrenArr.length; k++) {
        if (childrenArr[k].name == childName) {
          jsonArr2[j] = childrenArr[k];
          break;
        }
        ;
      }
      ;
    }
    ;
    setTree(child, jsonArr2, depth + 1);
  }
  ;
}

function showTree(json, depth) {
  console.log(depth + ":" + json.name + ":" + json.value);
  if (!json.children) {
    return;
  }
  ;
  for (var i = 0; i < json.children.length; i++) {
    var child = json.children[i];

    showTree(child, depth + 1);
  }
  ;
}

function setTree2(json, totalValue,totalValueWithoutEnd,parentDx, parentX) {

  if (json.name != "root") {
    if (totalValueWithoutEnd !=0 ) {
      json.pe = (100 * json.value / totalValueWithoutEnd).toPrecision(3) + "%";
      };
    json.dx = parentDx * (json.value / totalValue);
    json.x = parentX;
  }
  ;
  var nx = json.x;
  var ndx = json.dx;
  if (!json.children) {
    return;
  }
  ;
  var newTotalValue = 0;
  var newTotalValueWithoutEnd = 0;
  for (var i = 0; i < json.children.length; i++) {
    var child = json.children[i];
    newTotalValue = newTotalValue + child.value;
    if (child.name!="end") {
      newTotalValueWithoutEnd = newTotalValueWithoutEnd + child.value;
    };

  }
  ;

  var newX = 0.0;
  for (var i = 0; i < json.children.length; i++) {
    var child = json.children[i];

    if (i == 0) {
      newX = nx;
    } else {
      newX = json.children[i - 1].x + json.children[i - 1].dx;
    }
    setTree2(child, newTotalValue,newTotalValueWithoutEnd, ndx, newX);
  }
  ;
}

// Main function to draw and set up the visualization, once we have the data.
function createVisualization(jsonArr) {

  var json = jsonArr[jsonArr.length - 1];
  // Basic setup of page elements.
  initializeBreadcrumbTrail();
  drawLegend();
  d3.select("#togglelegend").on("click", toggleLegend);

  // Bounding circle underneath the sunburst, to make it easier to detect
  // when the mouse leaves the parent g.
  vis.append("svg:circle").attr("r", radius).style("opacity", 0);

  // For efficiency, filter nodes to keep only those large enough to see.
  var nodes = partition.nodes(json).filter(function(d) {
    return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
  });


  var arr = new Array();
  for (var i = 0; i < jsonArr.length - 1; i++) {
    partition.nodes(jsonArr[i]).filter(function(d) {
      return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
    });
    arr[i] = jsonArr[i];
  }
  ;

  setTree(json, arr, 0);
  setTree2(json, 0 , 0);

  var path = vis.data([ json ]).selectAll("path").data(nodes).enter().append(
      "svg:path").attr("display", function(d) {
    return d.depth ? null : "none";
  }).attr("d", arc).attr("fill-rule", "evenodd").style("fill", function(d) {
    return colors[d.name];
  }).style("opacity", 1).on("mouseover", mouseover);

  // Add the mouseleave handler to the bounding circle.
  d3.select("#container").on("mouseleave", mouseleave);

  // Get total size of the tree = value of root node from partition.
  totalSize = path.node().__data__.value;

};

// Fade all but the current sequence, and show it in the breadcrumb trail.
function mouseover(d) {
  initializeBreadcrumbTrail();
  var percentage = (100 * d.value / totalSize).toPrecision(3);
  var percentageString = percentage + "%";
  if (percentage < 0.1) {
    percentageString = "< 0.1%";
  }

  d3.select("#percentage").text(percentageString);

  d3.select("#explanation").style("visibility", "");

  var sequenceArray = getAncestors(d);

  updateBreadcrumbs(sequenceArray, percentageString);

  // Fade all the segments.
  d3.selectAll("path").style("opacity", 0.3);

  // Then highlight only those that are an ancestor of the current segment.
  vis.selectAll("path").filter(function(node) {
    return (sequenceArray.indexOf(node) >= 0);
  }).style("opacity", 1);
}

// Restore everything to full opacity when moving off the visualization.
function mouseleave(d) {

  // console.log(d);
  // Hide the breadcrumb trail
  d3.select("#trail").style("visibility", "hidden");

  // Deactivate all segments during transition.
  d3.selectAll("path").on("mouseover", null);

  // Transition each segment to full opacity and then reactivate it.
  d3.selectAll("path").transition().duration(1000).style("opacity", 1).each(
      "end", function() {
        d3.select(this).on("mouseover", mouseover);
      });

  d3.select("#explanation").style("visibility", "hidden");
}

// Given a node in a partition layout, return an array of all of its ancestor
// nodes, highest first, but excluding the root.
function getAncestors(node) {
  var path = [];
  var current = node;
  while (current.parent) {
    path.unshift(current);
    current = current.parent;
  }
  return path;
}

function initializeBreadcrumbTrail() {
  // Add the svg area.
  var seq = d3.select("#trail");
  // console.log(seq);
  if (seq) {
    seq.remove();
  }
  ;
  /*
   * while(seq!=null || seq.hasChildNodes()) //当div下还存在子节点时 循环继续 {
   * seq.removeChild(seq.firstChild); }
   */

  var trail = d3.select("#sequence").append("svg:svg").attr("width", width)
      .attr("height", 100).attr("id", "trail");

  // Add the label at the end, for the percentage.
  trail.append("svg:text").attr("id", "endlabel").style("fill", "#000");
}

// Generate a string that describes the points of a breadcrumb polygon.
function breadcrumbPoints(d, i) {
  var points = [];
  points.push("0,0");
  points.push(b.w + ",0");
  points.push(b.w + b.t + "," + (b.h / 2));
  points.push(b.w + "," + b.h);
  points.push("0," + b.h);
  if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex.
    points.push(b.t + "," + (b.h / 2));
  }
  return points.join(" ");
}

// Update the breadcrumb trail to show the current sequence and percentage.
function updateBreadcrumbs(nodeArray, percentageString) {

  // Data join; key function combines name and depth (= position in sequence).
  var g = d3.select("#trail").selectAll("g").data(nodeArray, function(d) {
    return d.name + d.depth;
  });

  // Add breadcrumb and label for entering nodes.
  var entering = g.enter().append("svg:g");

  entering.append("svg:polygon").attr("points", breadcrumbPoints).style(
      "fill", function(d) {
        return colors[d.name];
      });

  var text = entering.append("svg:text").attr("x", (b.w + b.t) / 2).attr("y",
      b.h / 4).attr("dy", "0.35em").attr("text-anchor", "middle")
  // .text(function(d) {return d.name+"|"+(100 *
  // d.value/d.parent.value).toPrecision(3)+"%|"+d.value});

  text.selectAll("tspan").data(
      function(d) {
        return [ d.name, d.pe,
            (100 * d.value / d.parent.value).toPrecision(3) + "%",
            (d.value / 10000).toPrecision(4) + "w" ];
      }).enter().append("tspan").attr("x", text.attr("x")).attr("dy",
      "1em").text(function(d) {
    return d
  });

  //

  // Set position for entering and updating nodes.
  g.attr("transform", function(d, i) {
    return "translate(" + i * (b.w + b.s) + ", 0)";
  });

  // Remove exiting nodes.
  g.exit().remove();

  // Now move and update the percentage at the end.
  d3.select("#trail").select("#endlabel").attr("x",
      (nodeArray.length + 0.5) * (b.w + b.s)).attr("y", b.h / 2).attr(
      "dy", "0.35em").attr("text-anchor", "middle")
      .text(percentageString);

  // Make the breadcrumb trail visible, if it's hidden.
  d3.select("#trail").style("visibility", "");

}

function drawLegend() {

  // Dimensions of legend item: width, height, spacing, radius of rounded
  // rect.
  var li = {
    w : 75,
    h : 30,
    s : 3,
    r : 3
  };

  var legend = d3.select("#legend").append("svg:svg").attr("width", li.w)
      .attr("height", d3.keys(colors).length * (li.h + li.s));

  var g = legend.selectAll("g").data(d3.entries(colors)).enter().append(
      "svg:g").attr("transform", function(d, i) {
    return "translate(0," + i * (li.h + li.s) + ")";
  });

  g.append("svg:rect").attr("rx", li.r).attr("ry", li.r).attr("width", li.w)
      .attr("height", li.h).style("fill", function(d) {
        return d.value;
      });

  g.append("svg:text").attr("x", li.w / 2).attr("y", li.h / 2).attr("dy",
      "0.35em").attr("text-anchor", "middle").text(function(d) {
    return d.key;
  });
}

function toggleLegend() {
  var legend = d3.select("#legend");
  if (legend.style("visibility") == "hidden") {
    legend.style("visibility", "");
  } else {
    legend.style("visibility", "hidden");
  }
}

// Take a 2-column CSV and transform it into a hierarchical structure suitable
// for a partition layout. The first column is a sequence of step names, from
// root to leaf, separated by hyphens. The second column is a count of how
// often that sequence occurred.
function buildHierarchy(csv) {
  var root = {
    "name" : "root",
    "children" : []
  };
  /*
   * console.log('root'); console.log(root);
   */
  for (var i = 0; i < csv.length; i++) {
    var sequence = csv[i][0];
    var size = +csv[i][1];
    // console.log("size"+size);
    if (isNaN(size)) { // e.g. if this is a header row
      continue;
    }
    var parts = sequence.split("-");
    var currentNode = root;
    for (var j = 0; j < parts.length; j++) {
      var children = currentNode["children"];
      var nodeName = parts[j];
      var childNode;
      if (j + 1 < parts.length) {
        // Not yet at the end of the sequence; move down the tree.
        var foundChild = false;
        for (var k = 0; k < children.length; k++) {
          if (children[k]["name"] == nodeName) {
            childNode = children[k];
            foundChild = true;
            break;
          }
        }
        // If we don't already have a child node for this branch, create
        // it.
        if (!foundChild) {
          childNode = {
            "name" : nodeName,
            "children" : []
          };
          children.push(childNode);
        }
        currentNode = childNode;
      } else {
        // Reached the end of the sequence; create a leaf node.
        childNode = {
          "name" : nodeName,
          "size" : size
        };
        children.push(childNode);
      }
    }
  }
  return root;
};